package com.liruo.srpingframework.dataaccess.transaction.savepoint;

import com.liruo.srpingframework.dataaccess.transaction.TransactionEntity;
import com.liruo.srpingframework.dataaccess.transaction.TransactionEntityRepository;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

@Slf4j
@Service
@Transactional
public class MultiRequestOrAllTransactionInAnPhysicalTransactionService {
  @Resource
  private TransactionEntityRepository repository;
  private MultiRequestOrAllTransactionInAnPhysicalTransactionService proxy(){
    return (MultiRequestOrAllTransactionInAnPhysicalTransactionService)AopContext.currentProxy();
  }

  private void doUpdate(String name){
    repository.save(new TransactionEntity(null, name));
  }

  public void transaction1() {
    log.info("transaction1: start");
    TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
    Object savepoint1 = status.createSavepoint();
    doUpdate("transaction1");
    log.info("transaction1: has error, rollback to savepoint = {}", savepoint1);
    status.rollbackToSavepoint(savepoint1);

    log.info("transaction1: solve the error, continue");
    doUpdate("transaction1-resolved error");
    proxy().transaction2();
  }

  public void transaction2() {
    log.info("transaction2: start");
    TransactionStatus status = TransactionAspectSupport.currentTransactionStatus();
    Object savepoint1 = status.createSavepoint();
    doUpdate("transaction2");
    log.info("transaction2: has error, rollback to savepoint = {}", savepoint1);
    status.rollbackToSavepoint(savepoint1);

    log.info("transaction2: solve the error, continue");
    doUpdate("transaction2-resolved error");
    proxy().transaction3();
  }

  public static final String ERROR = "transaction3 error";
  public void transaction3() {
    //tm.GlobalRollbackOnParticipationFailure default is true,
    // so don't need TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    log.info("transaction3: start");
    doUpdate("transaction3");
    log.info("transaction3: has error, can't handler it, throw to rollback and commit this transaction");
    throw new RuntimeException(ERROR);
    // doUpdate("transaction3-resolved error");
    //proxy().transaction4();
  }

  public void transaction4() {
    log.info("transaction4");
  }
}
